package com.irdstudio.bhcredit.agent.datasource;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Primary;

import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.alibaba.druid.wall.WallConfig;
import com.alibaba.druid.wall.WallFilter;
import com.irdstudio.basic.framework.core.util.PropertiesUtil;
import com.irdstudio.basic.framework.core.util.RSAUtility;

@Configuration
public class DruidConfig {
	
	private static final Logger logger = LoggerFactory.getLogger(DruidConfig.class);

	@Value("${dataSource.url}")
	private String dbUrl;

	@Value("${dataSource.username}")
	private String username;

	@Value("${dataSource.password}")
	private String password;

	@Value("${dataSource.driverClassName}")
	private String driverClassName;

	@Value("${dataSource.initialSize}")
	private int initialSize;

	@Value("${dataSource.minIdle}")
	private int minIdle;

	@Value("${dataSource.maxActive}")
	private int maxActive;

	@Value("${dataSource.maxWait}")
	private int maxWait;

	@Value("${dataSource.timeBetweenEvictionRunsMillis}")
	private int timeBetweenEvictionRunsMillis;

	@Value("${dataSource.minEvictableIdleTimeMillis}")
	private int minEvictableIdleTimeMillis;

	@Value("${dataSource.validationQuery}")
	private String validationQuery;

	@Value("${dataSource.testWhileIdle}")
	private boolean testWhileIdle;

	@Value("${dataSource.testOnBorrow}")
	private boolean testOnBorrow;

	@Value("${dataSource.testOnReturn}")
	private boolean testOnReturn;

	@Value("${dataSource.poolPreparedStatements}")
	private boolean poolPreparedStatements;

	@Value("${dataSource.filters}")
	private String filters;

	@Value("${dataSource.logSlowSql}")
	private String logSlowSql;
	
	@Value("${dataSource.connectionProperties}")
	private String connectionProperties;
	
	@Value("${dataSource.maxPoolPreparedStatementPerConnectionSize}")
	private int maxPoolPreparedStatementPerConnectionSize;
	
	@Value("${dataSource.removeAbandonedTimeout}")
	private int removeAbandonedTimeout ;
	
	@Value("${dataSource.logAbandoned}")
	private boolean logAbandoned ;

	@Autowired
	WallFilter wallFilter;
	
	@Bean
	@Primary
	public DataSource dataSource() throws Exception {
		// @Primary 注解作用是当程序选择dataSource时选择被注解的这个
		DruidDataSource datasource = new DruidDataSource();
		datasource.setUrl(dbUrl);
		datasource.setUsername(RSAUtility.decryptByBase64(username, PropertiesUtil.getPropertyByKey("key", "rsa.privateKey")));
		datasource.setPassword(RSAUtility.decryptByBase64(password, PropertiesUtil.getPropertyByKey("key", "rsa.privateKey")));
		datasource.setDriverClassName(driverClassName);
		datasource.setInitialSize(initialSize);
		datasource.setMinIdle(minIdle);
		datasource.setMaxActive(maxActive);
		datasource.setMaxWait(maxWait);
		datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
		datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
		datasource.setValidationQuery(validationQuery);
		datasource.setTestWhileIdle(testWhileIdle);
		datasource.setTestOnBorrow(testOnBorrow);
		datasource.setTestOnReturn(testOnReturn);
		datasource.setPoolPreparedStatements(poolPreparedStatements);
		datasource.setConnectionProperties(connectionProperties);
		datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
		datasource.setRemoveAbandonedTimeout(removeAbandonedTimeout);
		datasource.setLogAbandoned(logAbandoned);
		List<Filter> filter = new ArrayList<>();
		filter.add(wallFilter);
		datasource.setProxyFilters(filter);
		try {
			datasource.setFilters(filters);
		} catch (SQLException e) {
			logger.error("数据源初始化错误", e);
		}
		return datasource;
	}

	@Bean
	public ServletRegistrationBean druidServlet() throws Exception {
		ServletRegistrationBean reg = new ServletRegistrationBean();
		reg.setServlet(new StatViewServlet());
		reg.addUrlMappings("/druid/*");
		reg.addInitParameter("loginUsername", RSAUtility.decryptByBase64(username, PropertiesUtil.getPropertyByKey("key", "rsa.privateKey")));
		reg.addInitParameter("loginPassword", RSAUtility.decryptByBase64(password, PropertiesUtil.getPropertyByKey("key", "rsa.privateKey")));
		reg.addInitParameter("logSlowSql", logSlowSql);
		return reg;
	}

	@Bean
	public FilterRegistrationBean filterRegistrationBean() {
		FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
		filterRegistrationBean.setFilter(new WebStatFilter());
		filterRegistrationBean.addUrlPatterns("/*");
		filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
		filterRegistrationBean.addInitParameter("profileEnable", "true");
		return filterRegistrationBean;
	}
	
	@Bean(name ="wallConfig")
	WallConfig wallFilterConfiug(){
		WallConfig wc = new WallConfig();
		wc.setMultiStatementAllow(true);
		wc.setNoneBaseStatementAllow(true);
		return wc;
	}
	@Bean(name = "wallFilter")
	@DependsOn("wallConfig")
	WallFilter wallFilter(WallConfig wallConfig){
		WallFilter wallFilter = new WallFilter();
		wallFilter.setConfig(wallConfig);
		return wallFilter;
	}
}
